home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Utilities / MView / mview.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-30  |  57.7 KB  |  1,863 lines

  1. /*//////////////////////////////////////////////////////////////////////////////
  2. //
  3. // File: mview.cpp
  4. //
  5. // Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  6. //
  7. //
  8. //////////////////////////////////////////////////////////////////////////////*/
  9.  
  10. #include "mviewpch.h"
  11. #include <direct.h>
  12. #include "dxerr8.h"
  13.  
  14. TrivialData *g_pData = NULL;
  15.  
  16. //BOOL WINAPI D3DXDumpUnfreedMemoryInfo();
  17.  
  18. //-----------------------------------------------------------------------------
  19. // Name: D3DUtil_InitMaterial()
  20. // Desc: Helper function called to build a D3DMATERIAL structure
  21. //-----------------------------------------------------------------------------
  22. VOID D3DUtil_InitMaterial( D3DMATERIAL9& mtrl, FLOAT r, FLOAT g, FLOAT b )
  23. {
  24.     ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) );
  25.     mtrl.Diffuse.r = mtrl.Ambient.r = r;
  26.     mtrl.Diffuse.g = mtrl.Ambient.g = g;
  27.     mtrl.Diffuse.b = mtrl.Ambient.b = b;
  28.     mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
  29.     mtrl.Emissive.r = 0;
  30.     mtrl.Emissive.g = 0;
  31.     mtrl.Emissive.b = 0;
  32. }
  33.  
  34. TrivialData::TrivialData( )
  35. {
  36.     m_bTextureMode = TRUE;
  37.     m_bEdgeMode = FALSE;
  38.     m_bNPatchEdgeMode = FALSE;
  39.     m_bStripMode = FALSE;
  40.     m_bAdjacencyMode = FALSE;
  41.     m_bCreaseMode = FALSE;
  42.     m_bNormalsMode = FALSE;
  43.     m_bWireframeMode = FALSE;
  44.     m_bFaceSelectionMode = FALSE;
  45.     m_bVertexSelectionMode = FALSE;
  46.     m_bShowMeshSelectionMode = FALSE;
  47.     m_bAnimPaused = FALSE;
  48.     m_bLighting = TRUE;
  49.     m_bUpdatedNormalDuringMouseMove = FALSE;
  50.     m_dwTexCoordsShown = 0;
  51.  
  52.     m_hMenu = NULL;
  53.     m_hMeshMenu = NULL;
  54.     m_hAnimationsMenu = NULL;
  55.  
  56.     m_pmcSelectedMesh = NULL;
  57.     m_pframeSelected = NULL;
  58.     m_dwFaceSelected = UNUSED32;
  59.     m_dwVertexSelected = UNUSED32;
  60.     m_pdeHead = NULL;
  61.     m_pdeSelected = NULL;
  62.  
  63.     m_pfxFaceSelect = NULL;
  64.     m_pfxVertSelect = NULL;
  65.     m_pfxShowNormals = NULL;
  66.     m_pfxSkinnedAdjacency = NULL;
  67.  
  68.     m_pfvTreeView = NULL;
  69.  
  70.     m_dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL | D3DFVF_TEX1;
  71.  
  72.     m_sizeClient.cx = 0;
  73.     m_sizeClient.cy = 0;
  74.  
  75.     m_ptcTextureCacheHead = NULL;
  76.     m_method = D3DNONINDEXED;
  77.     m_iPaletteSize = x_iDefaultSkinningPaletteSize;
  78.  
  79.     m_rgbFontColor = 0;
  80.     m_hFontText = NULL;
  81.     m_fExtrusion = 0.1f;
  82.     m_fDeviation = 0.001f;
  83.     strcpy(m_szText, "Hello");
  84.  
  85.     m_bDisableHWNPatches = FALSE;
  86.     m_bForceSoftwareMode = FALSE;
  87.     m_bForceRefRast = FALSE;
  88.     m_bInitialFilename = FALSE;
  89.  
  90.     m_dwCullMode = D3DCULL_CCW;
  91.  
  92.     //m_fTicksPerSecond = 30.0f;
  93.     m_fTicksPerSecond = 4800.0f;
  94.  
  95.     m_fFramesPerSec = 0.0f;
  96.     m_fFramesPerSecCur = 0.0f;
  97.     m_fLastUpdateTime = 0.0f;
  98.     m_fTime = 0.0f;
  99. }
  100.  
  101. TrivialData::~TrivialData( )
  102. {
  103. #if 0
  104.     ReleaseFontAndTextBuffers();
  105. #endif
  106.  
  107.     delete m_pdeHead;
  108.  
  109.     delete m_pfvTreeView;
  110. }
  111.  
  112. HRESULT FrameViewSelectionCallback(PVOID pvCallbackData, PVOID pvItemId)
  113. {
  114.     TrivialData *pData = (TrivialData*)pvCallbackData;
  115.     SFrame *pframeSelected = (SFrame*)pvItemId;
  116.  
  117.     return pData->SelectFrame(pframeSelected, NULL);
  118. }
  119.  
  120. HRESULT TrivialData::SelectFrame(SFrame *pframeNew, SMeshContainer *pmcMesh)
  121. {
  122.     if (pframeNew != NULL)
  123.     {
  124.         m_pfvTreeView->SelectItem(pframeNew->m_hTreeHandle);
  125.  
  126.         // if selecting a new frame, unselect the face
  127.         if (pframeNew != m_pframeSelected)
  128.         {
  129.             SelectFace(UNUSED32);
  130.             SelectVertex(UNUSED32);
  131.         }
  132.  
  133.         m_pframeSelected = pframeNew;
  134.  
  135.         if (pmcMesh == NULL)
  136.             m_pmcSelectedMesh = pframeNew->pmcMesh;
  137.         else 
  138.             m_pmcSelectedMesh = pmcMesh;
  139.  
  140.         AdjustScrollbar();
  141.     }
  142.  
  143.     return S_OK;
  144. }
  145.  
  146. // mark a face as selected
  147. HRESULT TrivialData::SelectFace(DWORD dwFace)
  148. {
  149.     DWORD cAttr;
  150.     DWORD iAttr;
  151.     D3DXATTRIBUTERANGE *rgaeTable;
  152.  
  153.     if (dwFace == UNUSED32)
  154.     {
  155.         m_dwFaceSelected = UNUSED32;
  156.         m_dwFaceSelectedAttr = 0;
  157.     }
  158.     else
  159.     {
  160.         GXASSERT(m_pmcSelectedMesh != NULL);
  161.         GXASSERT(m_pmcSelectedMesh->ptmDrawMesh != NULL);
  162.  
  163.         m_dwFaceSelected = dwFace;
  164.         m_dwFaceSelectedAttr = 0;
  165.  
  166.         m_pmcSelectedMesh->ptmDrawMesh->GetAttributeTable(NULL, &cAttr);
  167.         if (cAttr > 0)
  168.         {
  169.             rgaeTable = (D3DXATTRIBUTERANGE*)_alloca(sizeof(D3DXATTRIBUTERANGE) * cAttr);
  170.  
  171.             // if tesselating, the attribute table must be the one tesselated from since the
  172.             //   selected face is from there
  173.             if (m_pmcSelectedMesh->pMeshToTesselate == NULL)
  174.                 m_pmcSelectedMesh->ptmDrawMesh->GetAttributeTable(rgaeTable, NULL);
  175.             else
  176.                 m_pmcSelectedMesh->pMeshToTesselate->GetAttributeTable(rgaeTable, NULL);
  177.  
  178.             for (iAttr = 0; iAttr < cAttr; iAttr++)
  179.             {
  180.                 if ((rgaeTable[iAttr].FaceStart <= dwFace) && ((rgaeTable[iAttr].FaceStart + rgaeTable[iAttr].FaceCount) > dwFace))
  181.                 {
  182.                     m_dwFaceSelectedAttr = iAttr;
  183.                     break;
  184.                 }
  185.             }
  186.         }
  187.     }
  188.  
  189.     return S_OK;
  190. }
  191.  
  192.  
  193. // mark a face as selected
  194. HRESULT TrivialData::SelectVertex(DWORD dwVertex)
  195. {
  196.     if (dwVertex == UNUSED32)
  197.     {
  198.         m_dwVertexSelected = UNUSED32;
  199.     }
  200.     else
  201.     {
  202.         GXASSERT(m_pmcSelectedMesh != NULL);
  203.         GXASSERT(m_pmcSelectedMesh->ptmDrawMesh != NULL);
  204.  
  205.         m_dwVertexSelected = dwVertex;
  206.     }
  207.  
  208.     return S_OK;
  209. }
  210.  
  211. BOOL TrivialData::AreCapsSufficient(D3DCAPS9 *pCaps, DWORD dwBehaviorFlags)
  212. {
  213.     if(pCaps->AdapterOrdinal != 0)
  214.         return FALSE;
  215.  
  216.     if(m_bForceRefRast && (pCaps->DeviceType != D3DDEVTYPE_REF))
  217.         return FALSE;
  218.  
  219.     //if (dwBehaviorFlags == D3DCREATE_HARDWARE_VERTEXPROCESSING)
  220.         //return FALSE;
  221.         //return TRUE;
  222.     if (dwBehaviorFlags == D3DCREATE_MIXED_VERTEXPROCESSING)
  223.         return !m_bForceSoftwareMode;
  224.  
  225.     if (dwBehaviorFlags == D3DCREATE_SOFTWARE_VERTEXPROCESSING)
  226.         return TRUE;
  227.  
  228.     return FALSE;//TRUE;    // TODO
  229. }
  230.  
  231. void
  232. TrivialData::SetupMenu()
  233. {
  234.     BOOL bSelectedContainer = FALSE;
  235.     BOOL bPMMode = FALSE;
  236.     BOOL bSelectedMesh = FALSE;
  237.     BOOL bTessellateMode = FALSE;
  238.     BOOL bNPatchMode = FALSE;
  239.     BOOL bAnimPresent = FALSE;
  240.     BOOL bSoftwareSkinning = (m_method == SOFTWARE);
  241.  
  242.     if (m_pmcSelectedMesh != NULL)
  243.     {
  244.         bSelectedContainer = TRUE;
  245.  
  246.         // first pmesh only menu items
  247.         bPMMode =  m_pmcSelectedMesh->bPMMeshMode;
  248.         bTessellateMode = m_pmcSelectedMesh->bTesselateMode;
  249.         bNPatchMode = m_pmcSelectedMesh->bNPatchMode;
  250.  
  251.         bSelectedMesh = (m_pmcSelectedMesh->pMesh != NULL) && !m_pmcSelectedMesh->bPMMeshMode && !m_pmcSelectedMesh->bSimplifyMode && !m_pmcSelectedMesh->bTesselateMode && !m_pmcSelectedMesh->bNPatchMode;
  252.     }
  253.  
  254.     if (m_pdeHead != NULL)
  255.     {
  256.         bAnimPresent = (m_pdeHead->m_pAnimMixer != NULL);
  257.     }
  258.  
  259.     // enable/gray menu items requiring something loaded
  260.     EnableMenuItem(m_hMenu, ID_FILE_CLOSEMESH, bSelectedContainer ? MF_ENABLED : MF_GRAYED);
  261.     EnableMenuItem(m_hMenu, ID_FILE_CLOSENONSELECTED, bSelectedContainer ? MF_ENABLED : MF_GRAYED);
  262.     EnableMenuItem(m_hMenu, ID_OPTIONS_RESETMATRICES, bSelectedContainer ? MF_ENABLED : MF_GRAYED);
  263.     EnableMenuItem(m_hMenu, ID_OPTIONS_PROPERTIES, bSelectedContainer ? MF_ENABLED : MF_GRAYED);
  264.     EnableMenuItem(m_hMenu, ID_FILE_SAVEMESH, (m_pdeHead != NULL) ? MF_ENABLED : MF_GRAYED);
  265.  
  266.     EnableMenuItem(m_hMenu, ID_MESHOPS_COLLAPSE, (m_pdeSelected != NULL) ? MF_ENABLED : MF_GRAYED);
  267.  
  268.     // enable/gray menu items requiring a "normal" mesh selected
  269.     EnableMenuItem(m_hMenu, ID_SIMPLIFY_GENERATEPM, bSelectedMesh ? MF_ENABLED : MF_GRAYED);
  270.     EnableMenuItem(m_hMenu, ID_OPTIONS_COMPACT, bSelectedMesh ? MF_ENABLED : MF_GRAYED);
  271.     EnableMenuItem(m_hMenu, ID_OPTIONS_ATTRSORT, bSelectedMesh ? MF_ENABLED : MF_GRAYED);
  272.     EnableMenuItem(m_hMenu, ID_OPTIONS_STRIPREORDER, bSelectedMesh ? MF_ENABLED : MF_GRAYED);
  273.     EnableMenuItem(m_hMenu, ID_OPTIONS_VERTEXCACHE, bSelectedMesh ? MF_ENABLED : MF_GRAYED);
  274.     EnableMenuItem(m_hMenu, ID_OPTIMIZE_SIMULATE, bSelectedMesh ? MF_ENABLED : MF_GRAYED);
  275.     EnableMenuItem(m_hMenu, ID_OPTIONS_WELDVERTICES, bSelectedMesh ? MF_ENABLED : MF_GRAYED);
  276.     EnableMenuItem(m_hMenu, ID_OPTIONS_NPATCHFRAME, bSelectedMesh ? MF_ENABLED : MF_GRAYED);
  277.     EnableMenuItem(m_hMenu, ID_OPTIONS_SPLITMESH, bSelectedMesh ? MF_ENABLED : MF_GRAYED);
  278.     EnableMenuItem(m_hMenu, ID_OPTIONS_APPLYDISPLACEMENT, bSelectedMesh ? MF_ENABLED : MF_GRAYED);
  279.     EnableMenuItem(m_hMenu, ID_FILE_SAVEMESHTOM, bSelectedMesh ? MF_ENABLED : MF_GRAYED);
  280.     EnableMenuItem(m_hMenu, ID_MESHOPS_COMPUTENORMALS, bSelectedMesh ? MF_ENABLED : MF_GRAYED);
  281.     EnableMenuItem(m_hMenu, ID_MESHOPS_VALIDATEMESH, bSelectedMesh ? MF_ENABLED : MF_GRAYED);
  282.  
  283.     // enable/gray pmesh menu items
  284.     EnableMenuItem(m_hMenu, ID_SIMPLIFY_SIMPLIFY, bPMMode ? MF_ENABLED : MF_GRAYED);
  285.     EnableMenuItem(m_hMenu, ID_SIMPLIFY_SIMPLIFYFACES, bPMMode ? MF_ENABLED : MF_GRAYED);
  286.     EnableMenuItem(m_hMenu, ID_SIMPLIFY_SETSOFTMIN, bPMMode ? MF_ENABLED : MF_GRAYED);
  287.     EnableMenuItem(m_hMenu, ID_SIMPLIFY_SETSOFTMAX, bPMMode ? MF_ENABLED : MF_GRAYED);
  288.     EnableMenuItem(m_hMenu, ID_SIMPLIFY_RESETSOFTMIN, bPMMode ? MF_ENABLED : MF_GRAYED);
  289.     EnableMenuItem(m_hMenu, ID_SIMPLIFY_RESETSOFTMAX, bPMMode ? MF_ENABLED : MF_GRAYED);
  290.     EnableMenuItem(m_hMenu, ID_SIMPLIFY_TRIM, bPMMode ? MF_ENABLED : MF_GRAYED);
  291.     EnableMenuItem(m_hMenu, ID_SIMPLIFY_SNAPSHOT, bPMMode ? MF_ENABLED : MF_GRAYED);
  292.  
  293.     // enable/gray tessellate menu items
  294.     //  UNDONE UNDONE - need to add patch menus instead of piggybacking on npatches
  295.     EnableMenuItem(m_hMenu, ID_NPATCHES_SNAPSHOT, (bNPatchMode || bTessellateMode) ? MF_ENABLED : MF_GRAYED);
  296.     EnableMenuItem(m_hMenu, ID_NPATCHES_EDGEMODE, bNPatchMode ? MF_ENABLED : MF_GRAYED);
  297.     CheckMenuItem(m_hMenu, ID_NPATCHES_EDGEMODE, m_bNPatchEdgeMode ? MF_CHECKED : MF_UNCHECKED);
  298.  
  299.     // setup check marks on menu's and toolbars
  300.     CheckMenuItem(m_hMenu, ID_D3D_EDGEMODE, m_bEdgeMode ? MF_CHECKED : MF_UNCHECKED);
  301.     CheckMenuItem(m_hMenu, ID_D3D_WIREFRAME, m_bWireframeMode ? MF_CHECKED : MF_UNCHECKED);
  302.     SendMessage(m_hwndToolbar, TB_CHECKBUTTON, ID_D3D_EDGEMODE, MAKELONG(m_bEdgeMode, 0));
  303.     SendMessage(m_hwndToolbar, TB_CHECKBUTTON, ID_D3D_WIREFRAME, MAKELONG(m_bWireframeMode, 0));
  304.     SendMessage(m_hwndToolbar, TB_CHECKBUTTON, ID_D3D_SOLID, MAKELONG((!m_bEdgeMode && !m_bWireframeMode), 0));
  305.  
  306.     CheckMenuItem(m_hMenu, ID_OPTIONS_VERTEXSELECTION, m_bVertexSelectionMode ? MF_CHECKED : MF_UNCHECKED);
  307.     CheckMenuItem(m_hMenu, ID_OPTIONS_FACESELECTION, m_bFaceSelectionMode ? MF_CHECKED : MF_UNCHECKED);
  308.     CheckMenuItem(m_hMenu, ID_OPTIONS_MESHSELECTION, m_bShowMeshSelectionMode ? MF_CHECKED : MF_UNCHECKED);
  309.     SendMessage(m_hwndToolbar, TB_CHECKBUTTON, ID_OPTIONS_VERTEXSELECTION, MAKELONG(m_bVertexSelectionMode, 0));
  310.     SendMessage(m_hwndToolbar, TB_CHECKBUTTON, ID_OPTIONS_FACESELECTION, MAKELONG(m_bFaceSelectionMode, 0));
  311.     SendMessage(m_hwndToolbar, TB_CHECKBUTTON, ID_OPTIONS_MESHSELECTION, MAKELONG(m_bShowMeshSelectionMode, 0));
  312.     SendMessage(m_hwndToolbar, TB_CHECKBUTTON, ID_OPTIONS_NOSELECTION, MAKELONG((!m_bFaceSelectionMode && !m_bVertexSelectionMode && !m_bShowMeshSelectionMode), 0));
  313.  
  314.     EnableMenuItem(m_hMenu, ID_D3D_ADJACENCYMODE, !bSoftwareSkinning && !bTessellateMode ? MF_ENABLED : MF_GRAYED);
  315.     SendMessage(m_hwndToolbar, TB_ENABLEBUTTON, ID_D3D_ADJACENCYMODE, MAKELONG(!(bSoftwareSkinning||bTessellateMode), 0));
  316.     CheckMenuItem(m_hMenu, ID_D3D_ADJACENCYMODE, m_bAdjacencyMode ? MF_CHECKED : MF_UNCHECKED);
  317.     SendMessage(m_hwndToolbar, TB_CHECKBUTTON, ID_D3D_ADJACENCYMODE, MAKELONG(m_bAdjacencyMode, 0));
  318.  
  319.     EnableMenuItem(m_hMenu, ID_D3D_CREASEMODE, !bSoftwareSkinning && !bTessellateMode ? MF_ENABLED : MF_GRAYED);
  320.     SendMessage(m_hwndToolbar, TB_ENABLEBUTTON, ID_D3D_CREASEMODE, MAKELONG(!(bSoftwareSkinning||bTessellateMode), 0));
  321.     CheckMenuItem(m_hMenu, ID_D3D_CREASEMODE, m_bCreaseMode ? MF_CHECKED : MF_UNCHECKED);
  322.     SendMessage(m_hwndToolbar, TB_CHECKBUTTON, ID_D3D_CREASEMODE, MAKELONG(m_bCreaseMode, 0));
  323.  
  324.     EnableMenuItem(m_hMenu, ID_D3D_STRIPMODE, !bSoftwareSkinning && !bTessellateMode ? MF_ENABLED : MF_GRAYED);
  325.     SendMessage(m_hwndToolbar, TB_ENABLEBUTTON, ID_D3D_STRIPMODE, MAKELONG(!(bSoftwareSkinning||bTessellateMode), 0));
  326.     CheckMenuItem(m_hMenu, ID_D3D_STRIPMODE, m_bStripMode ? MF_CHECKED : MF_UNCHECKED);
  327.     SendMessage(m_hwndToolbar, TB_CHECKBUTTON, ID_D3D_STRIPMODE, MAKELONG(m_bStripMode, 0));
  328.  
  329.     EnableMenuItem(m_hMenu, ID_D3D_SHOWNORMALS, !bSoftwareSkinning ? MF_ENABLED : MF_GRAYED);
  330.     SendMessage(m_hwndToolbar, TB_ENABLEBUTTON, ID_D3D_SHOWNORMALS, MAKELONG(!bSoftwareSkinning, 0));
  331.     CheckMenuItem(m_hMenu, ID_D3D_SHOWNORMALS, m_bNormalsMode ? MF_CHECKED : MF_UNCHECKED);
  332.     SendMessage(m_hwndToolbar, TB_CHECKBUTTON, ID_D3D_SHOWNORMALS, MAKELONG(m_bNormalsMode, 0));
  333.  
  334.  
  335.     CheckMenuItem(m_hMenu, ID_D3D_LIGHTING, m_bLighting ? MF_CHECKED : MF_UNCHECKED);
  336.     CheckMenuItem(m_hMenu, ID_D3D_CULL, (m_dwCullMode == D3DCULL_CCW) ? MF_CHECKED : MF_UNCHECKED);
  337.     CheckMenuItem(m_hMenu, ID_OPTIONS_TEXTURE, m_bTextureMode ? MF_CHECKED : MF_UNCHECKED);
  338.  
  339.     CheckMenuItem(m_hMenu, ID_D3D_SOFTWARESKIN, (m_method == SOFTWARE) ? MF_CHECKED : MF_UNCHECKED);
  340.     CheckMenuItem(m_hMenu, ID_D3D_INDEXED,      (m_method == D3DINDEXED) ? MF_CHECKED : MF_UNCHECKED);
  341.     CheckMenuItem(m_hMenu, ID_D3D_NONINDEXED,   (m_method == D3DNONINDEXED) ? MF_CHECKED : MF_UNCHECKED);
  342.  
  343.  
  344.     CheckMenuItem(m_hMenu, ID_VIEW_PLAYBACKSPEED, (m_fTicksPerSecond == 4800.0f) ? MF_CHECKED : MF_UNCHECKED);
  345.     EnableMenuItem(m_hMenu, ID_VIEW_PLAYANIM, (bAnimPresent && m_bAnimPaused) ? MF_ENABLED : MF_GRAYED);
  346.     EnableMenuItem(m_hMenu, ID_VIEW_PAUSEANIM, (bAnimPresent && !m_bAnimPaused) ? MF_ENABLED : MF_GRAYED);
  347.     CheckMenuItem(m_hMenu, ID_VIEW_PLAYANIM, (bAnimPresent && !m_bAnimPaused) ? MF_CHECKED : MF_UNCHECKED);
  348.     CheckMenuItem(m_hMenu, ID_VIEW_PAUSEANIM, (bAnimPresent && m_bAnimPaused) ? MF_CHECKED : MF_UNCHECKED);
  349.     SendMessage(m_hwndToolbar, TB_CHECKBUTTON, ID_VIEW_PLAYANIM, MAKELONG(bAnimPresent && !m_bAnimPaused, 0));
  350.     SendMessage(m_hwndToolbar, TB_CHECKBUTTON, ID_VIEW_PAUSEANIM, MAKELONG(bAnimPresent && m_bAnimPaused, 0));
  351.     SendMessage(m_hwndToolbar, TB_ENABLEBUTTON, ID_VIEW_PLAYANIM, MAKELONG(bAnimPresent, 0));
  352.     SendMessage(m_hwndToolbar, TB_ENABLEBUTTON, ID_VIEW_PAUSEANIM, MAKELONG(bAnimPresent, 0));
  353. }
  354.  
  355.  
  356. // go to each mesh container and reset all the effects
  357. HRESULT
  358. ResetEffects(SFrame *pframe, TrivialData *pApp)
  359. {
  360.     HRESULT hr = S_OK;
  361.     SMeshContainer *pmcCur = pframe->pmcMesh;
  362.     SFrame *pframeCur;
  363.     DWORD ifx;
  364.  
  365.     while (pmcCur != NULL)
  366.     {
  367.         for (ifx = 0; ifx < pmcCur->NumMaterials; ifx++)
  368.         {
  369.             if (pmcCur->m_rgpfxAttributes[ifx] != NULL)
  370.             {
  371.                 pmcCur->m_rgpfxAttributes[ifx]->OnResetDevice();
  372.             }
  373.         }
  374.  
  375.         pmcCur = (SMeshContainer*)pmcCur->pNextMeshContainer;
  376.     }
  377.  
  378.     pframeCur = pframe->pframeFirstChild;
  379.     while (pframeCur != NULL)
  380.     {
  381.         hr = ResetEffects(pframeCur, pApp);
  382.         if (FAILED(hr))
  383.             goto e_Exit;
  384.  
  385.         pframeCur = pframeCur->pframeSibling;
  386.     }
  387.  
  388. e_Exit:
  389.     return hr;
  390. }
  391.  
  392. HRESULT TrivialData::OnResetDevice()
  393. {
  394.     HRESULT hr = S_OK;
  395.     RECT r;
  396.     D3DLIGHT9 light;
  397.     D3DCAPS9 Caps;
  398.  
  399.     SetupMenu();
  400.  
  401.     GetClientRect( m_hwnd, &r );
  402.  
  403.     // setup the client rect size, used for frame rate info
  404.     m_sizeClient.cx = r.right - r.left;
  405.     m_sizeClient.cy = r.bottom - r.top;
  406.  
  407.     m_abArcBall.SetWindow(r.right, r.bottom, 0.85f);
  408.  
  409.     if (m_pdeSelected != NULL)
  410.         SetProjectionMatrix();
  411.  
  412.     //m_FPSMeter.OnResetDevice(m_hwnd, m_pDevice);    //
  413.  
  414.     m_pDevice->GetDeviceCaps(&Caps);
  415.     m_bHWVertexShaders = Caps.VertexShaderVersion >= D3DVS_VERSION(1,1);
  416.     m_bHWNPatches = !m_bDisableHWNPatches && (Caps.DevCaps & D3DDEVCAPS_NPATCHES);   
  417.     m_bSoftwareVP = FAILED(m_pDevice->SetSoftwareVertexProcessing(FALSE));
  418.  
  419.  
  420.     m_pDevice->SetRenderState( D3DRS_DITHERENABLE, TRUE );
  421.     m_pDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
  422.     m_pDevice->SetRenderState( D3DRS_SPECULARENABLE, TRUE );
  423.     m_pDevice->SetRenderState( D3DRS_NORMALIZENORMALS, TRUE );
  424.     m_pDevice->SetRenderState( D3DRS_AMBIENT,  0xffffffff);
  425.     m_pDevice->SetNPatchMode( 0 );
  426.     m_pDevice->SetRenderState( D3DRS_CULLMODE, m_dwCullMode );
  427.     m_pDevice->SetRenderState( D3DRS_LIGHTING, m_bLighting );
  428.  
  429.     m_pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR  );
  430.     m_pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR  );
  431.     m_pDevice->SetRenderState( D3DRS_FILLMODE, m_bWireframeMode ? D3DFILL_WIREFRAME : D3DFILL_SOLID);
  432.  
  433.     light.Type        = D3DLIGHT_DIRECTIONAL;
  434.  
  435.     light.Diffuse.r = 1.0;
  436.     light.Diffuse.g = 1.0;
  437.     light.Diffuse.b = 1.0;
  438.     light.Specular.r = 0;
  439.     light.Specular.g = 0;
  440.     light.Specular.b = 0;
  441.     //light.Ambient.r = 0.25;
  442.     //light.Ambient.g = 0.25;
  443.     //light.Ambient.b = 0.25;
  444.     light.Ambient.r = 1;
  445.     light.Ambient.g = 1;
  446.     light.Ambient.b = 1;
  447.  
  448.     light.Position     = D3DXVECTOR3(0.0f, 0.0f, -20.0f);
  449.     light.Direction    = D3DXVECTOR3( 0.0f, 0.0f, 1.0f);
  450.     light.Attenuation0 = 0.0f;
  451.     light.Attenuation1 = 0.0f;
  452.     light.Attenuation2 = 0.0f;
  453.     light.Range = ((float)sqrt(FLT_MAX));
  454.  
  455.     switch( light.Type )
  456.     {
  457.         case D3DLIGHT_POINT:
  458.             light.Attenuation0 = 1.0f;
  459.             break;
  460.         case D3DLIGHT_DIRECTIONAL:
  461.             light.Position     = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  462.             break;
  463.         case D3DLIGHT_SPOT:
  464.             light.Position     = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  465.             light.Range        =   1.0f;
  466.             light.Falloff      = 100.0f;
  467.             light.Theta        =   0.8f;
  468.             light.Phi          =   1.0f;
  469.             light.Attenuation2 =   1.0f;
  470.     }
  471.  
  472.     hr = m_pDevice->SetLight(0, &light );
  473.     if (FAILED(hr))
  474.         return E_FAIL;
  475.  
  476.     light.Diffuse.r = 0.5;
  477.     light.Diffuse.g = 0.5;
  478.     light.Diffuse.b = 0.5;
  479.  
  480.     hr = m_pDevice->SetLight(1, &light );
  481.     if (FAILED(hr))
  482.         return E_FAIL;
  483.  
  484.     hr = m_pDevice->LightEnable(0, TRUE);
  485.     if (FAILED(hr))
  486.         return E_FAIL;
  487.  
  488.     hr = m_pDevice->LightEnable(1, FALSE);
  489.     if (FAILED(hr))
  490.         return E_FAIL;
  491.  
  492.     // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the shader debugger.  
  493.     // Debugging vertex shaders requires either REF or software vertex processing, and debugging 
  494.     // pixel shaders requires REF.  The D3DXSHADER_FORCE_*_SOFTWARE_NOOPT flag improves the debug 
  495.     // experience in the shader debugger.  It enables source level debugging, prevents instruction 
  496.     // reordering, prevents dead code elimination, and forces the compiler to compile against the next 
  497.     // higher available software target, which ensures that the unoptimized shaders do not exceed 
  498.     // the shader model limitations.  Setting these flags will cause slower rendering since the shaders 
  499.     // will be unoptimized and forced into software.  See the DirectX documentation for more information 
  500.     // about using the shader debugger.
  501.     DWORD dwShaderFlags = 0;
  502.     #ifdef DEBUG_VS
  503.         dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
  504.     #endif
  505.     #ifdef DEBUG_PS
  506.         dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
  507.     #endif
  508.  
  509.     hr = D3DXCreateEffectFromResource(m_pDevice, NULL, MAKEINTRESOURCE(IDD_FACESELECT), NULL, NULL, dwShaderFlags, NULL, &m_pfxFaceSelect, NULL);
  510.     if (FAILED(hr))
  511.         return hr;
  512.  
  513.     hr = D3DXCreateEffectFromResource(m_pDevice, NULL, MAKEINTRESOURCE(IDD_VERTSELECT), NULL, NULL, dwShaderFlags, NULL, &m_pfxVertSelect, NULL);
  514.     if (FAILED(hr))
  515.         return hr;
  516.  
  517.     hr = D3DXCreateEffectFromResource(m_pDevice, NULL, MAKEINTRESOURCE(IDD_SHOWNORMALS), NULL, NULL, dwShaderFlags, NULL, &m_pfxShowNormals, NULL);
  518.     if (FAILED(hr))
  519.         return hr;
  520.  
  521.     //hr = D3DXCreateEffectFromFile(m_pDevice, "adjacency.fx", NULL, NULL, dwShaderFlags, NULL, &m_pfxSkinnedAdjacency, NULL);
  522.     hr = D3DXCreateEffectFromResource(m_pDevice, NULL, MAKEINTRESOURCE(IDD_ADJACENCY), NULL, NULL, dwShaderFlags, NULL, &m_pfxSkinnedAdjacency, NULL);
  523.     if (FAILED(hr))
  524.         return hr;
  525.  
  526.     if (m_pdeHead != NULL)
  527.     {
  528.         ResetEffects(m_pdeHead->pframeRoot, this);
  529.     }
  530.  
  531.     // a file was requested to be loaded on startup
  532.     if (m_bInitialFilename)
  533.     {
  534.         hr = LoadMeshHierarchyFromFile(m_szInitialFilename);
  535.         m_bInitialFilename = FALSE;
  536.  
  537.         if (FAILED(hr))
  538.         {
  539.             MessageBox( m_hwnd, "Unabled to load the specified file.", "Load failed!", MB_OK);
  540.             hr = S_OK;
  541.         }
  542.     }
  543.  
  544.     return S_OK;
  545. }
  546.  
  547. HRESULT TrivialData::OnDestroyDevice()
  548. {
  549.     //m_FPSMeter.OnDestroyDevice();   //
  550.  
  551.     delete m_pdeHead;
  552.     m_pdeHead = NULL;
  553.  
  554.     delete m_ptcTextureCacheHead;
  555.     m_ptcTextureCacheHead = NULL;
  556.  
  557.     return S_OK;
  558. }
  559.  
  560. HRESULT
  561. OnLostEffects(SFrame *pframe)
  562. {
  563.     HRESULT hr = S_OK;
  564.     SMeshContainer *pmcCur = pframe->pmcMesh;
  565.     SFrame *pframeCur;
  566.     DWORD ifx;
  567.  
  568.     while (pmcCur != NULL)
  569.     {
  570.         for (ifx = 0; ifx < pmcCur->NumMaterials; ifx++)
  571.         {
  572.             if (pmcCur->m_rgpfxAttributes[ifx] != NULL)
  573.             {
  574.                 pmcCur->m_rgpfxAttributes[ifx]->OnLostDevice();
  575.             }
  576.         }
  577.  
  578.         pmcCur = (SMeshContainer*)pmcCur->pNextMeshContainer;
  579.     }
  580.  
  581.     pframeCur = pframe->pframeFirstChild;
  582.     while (pframeCur != NULL)
  583.     {
  584.         hr = OnLostEffects(pframeCur);
  585.         if (FAILED(hr))
  586.             goto e_Exit;
  587.  
  588.         pframeCur = pframeCur->pframeSibling;
  589.     }
  590.  
  591. e_Exit:
  592.     return hr;
  593. }
  594.  
  595. HRESULT TrivialData::OnLostDevice()
  596. {
  597.     //m_FPSMeter.OnLostDevice();  //
  598.  
  599.     GXRELEASE(m_pfxFaceSelect);
  600.     GXRELEASE(m_pfxVertSelect);
  601.     GXRELEASE(m_pfxShowNormals);
  602.     GXRELEASE(m_pfxSkinnedAdjacency);
  603.  
  604.     if (m_pdeHead != NULL)
  605.     {
  606.         OnLostEffects(m_pdeHead->pframeRoot);
  607.     }
  608.  
  609.     return S_OK;
  610. }
  611.  
  612. HRESULT TrivialData::OnCreateDevice()
  613. {
  614.     HRESULT hr = S_OK;
  615.  
  616.     AdjustScrollbar();
  617.     SetProjectionMatrix();
  618.  
  619.     D3DCAPS9 caps;
  620.     hr = m_pDevice->GetDeviceCaps(&caps);
  621.     if (hr != S_OK)
  622.         return hr;
  623.     m_maxFaceInflHW = caps.MaxVertexBlendMatrices;
  624.  
  625.     if (m_pfvTreeView == NULL)
  626.     {
  627.         RECT rTreeView;
  628.  
  629.         GetWindowRect( m_hwnd, &rTreeView );
  630.         rTreeView.right =  rTreeView.left + (rTreeView.right - rTreeView.left) / 3;
  631.  
  632.         hr = CreateFrameView(rTreeView, m_hwnd, m_hInstance,
  633.                                     FrameViewSelectionCallback, (PVOID)this,
  634.                                     TrivialData::WndProcCallback,
  635.                                     &m_pfvTreeView);
  636.         if (FAILED(hr))
  637.             goto e_Exit;
  638.  
  639.         SetFocus(m_hwnd);
  640.     }
  641.  
  642.     m_ShowArcball.Init(m_pDevice, 64);
  643.  
  644.     // prepare
  645.  
  646. e_Exit:
  647.     return hr;
  648. }
  649.  
  650. void TrivialData::ToggleTreeView()
  651. {
  652.     BOOL bVisible;
  653.     RECT rTreeView;
  654.     RECT rWindowRect;
  655.  
  656.     // toggle visibility of tree view
  657.     bVisible = m_pfvTreeView->ToggleVisible();
  658.  
  659.     CheckMenuItem(m_hMenu, ID_OPTIONS_TREEVIEW, bVisible ? MF_CHECKED : MF_UNCHECKED);
  660.  
  661.     // if visible, make sure that the two windows don't overlap each other
  662.     if (bVisible)
  663.     {
  664.         m_pfvTreeView->GetWindowRect(&rTreeView);
  665.         GetWindowRect( m_hwnd, &rWindowRect );
  666.  
  667.         // if overlapping, move 
  668.         if (rWindowRect.left == rTreeView.left)
  669.         {
  670.             rWindowRect.left += (rTreeView.right - rTreeView.left);
  671.             rWindowRect.right += (rTreeView.right - rTreeView.left);
  672.  
  673.             SetWindowPos( m_hwnd, HWND_TOP, rWindowRect.left, rWindowRect.top,
  674.                                         rWindowRect.right - rWindowRect.left,
  675.                                         rWindowRect.bottom - rWindowRect.top, SWP_NOZORDER);
  676.         }
  677.     }
  678. }
  679.  
  680. void
  681. TrivialData::PauseDrawing( )
  682. {
  683.     //bPaused = true;
  684.  
  685. #if 0
  686.     if ( bFullScreen )
  687.     {
  688.         pDXMgr->FlipToGDISurface();
  689.         DrawMenuBar(m_hwnd);
  690.         RedrawWindow(m_hwnd, NULL, NULL, RDW_FRAME);
  691.     }
  692. #endif
  693. }
  694.  
  695. void
  696. TrivialData::RestartDrawing( )
  697. {
  698.     //bPaused = false;
  699. }
  700.  
  701. static BOOL CALLBACK
  702. EnumFirstResource(HINSTANCE hInstance, LPCTSTR lpszType, LPTSTR lpszName, LPARAM lParam)
  703. {
  704.     *((LPSTR *) lParam) = lpszName;
  705.     return FALSE;
  706. }
  707.  
  708. void
  709. TrivialData::InitializeHelper()
  710. {
  711.     HMENU hAnimMenu;
  712.     m_hMenu = GetMenu(m_hwnd);
  713.  
  714.     // get the animation sub-sub-menu
  715.     hAnimMenu = GetSubMenu(m_hMenu, 3);
  716.     m_hAnimationsMenu = GetSubMenu(hAnimMenu, 5);
  717.  
  718.     m_hFontText = CreateFont(
  719.         12,
  720.         0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
  721.         ANSI_CHARSET,
  722.         OUT_DEFAULT_PRECIS,
  723.         CLIP_DEFAULT_PRECIS,
  724.         DEFAULT_QUALITY,
  725.         VARIABLE_PITCH,
  726.         "Arial" );
  727.  
  728.     InitCommonControls();
  729.  
  730.     // Create the status bar. 
  731.     m_hwndStatus = CreateWindowEx( 
  732.         0,                       // no extended styles 
  733.         STATUSCLASSNAME,                // name of status bar class 
  734.         (LPCTSTR) NULL,          // no text when first created 
  735.         WS_CHILD | WS_VISIBLE,                // creates a child window 
  736.         0, 0, 0, 0,              // ignores size and position 
  737.         m_hwnd,                  // handle to parent window 
  738.         (HMENU) 0,               // child window identifier 
  739.         m_hInstance,             // handle to application instance 
  740.         NULL);                   // no window creation data 
  741.  
  742.  
  743.     RECT r;
  744.     INT lpParts[x_cStatusBarSizes+1];// = {280, 370, 430, 500, 560, 640};
  745.     DWORD iCur;
  746.     INT iPart;
  747.  
  748.     GetClientRect( m_hwnd, &r );
  749.     iCur = r.right - r.left;
  750.     for (iPart = x_cStatusBarSizes - 1; iPart >= 0; iPart--)
  751.     {
  752.         lpParts[iPart+1] = iCur;
  753.         iCur -= x_rgStatusBarSizes[iPart];
  754.     }
  755.     lpParts[0] = iCur;
  756.  
  757.     SendMessage(m_hwndStatus, SB_SETPARTS, (WPARAM) x_cStatusBarSizes+1, (LPARAM) lpParts); 
  758.  
  759.  
  760.     const DWORD cButtons = 18;
  761.     TBBUTTON Buttons[cButtons];
  762.  
  763.     Buttons[0].iBitmap = 0; 
  764.     Buttons[0].idCommand = ID_OPTIONS_NOSELECTION; 
  765.     Buttons[0].fsState = TBSTATE_ENABLED; 
  766.     Buttons[0].fsStyle = TBSTYLE_BUTTON; 
  767.     Buttons[0].dwData = 0; 
  768.     Buttons[0].iString = 0; 
  769.  
  770.     Buttons[1].iBitmap = 13; 
  771.     Buttons[1].idCommand = ID_OPTIONS_MESHSELECTION; 
  772.     Buttons[1].fsState = TBSTATE_ENABLED; 
  773.     Buttons[1].fsStyle = TBSTYLE_BUTTON; 
  774.     Buttons[1].dwData = 0; 
  775.     Buttons[1].iString = 0; 
  776.  
  777.     Buttons[2].iBitmap = 1; 
  778.     Buttons[2].idCommand = ID_OPTIONS_FACESELECTION; 
  779.     Buttons[2].fsState = TBSTATE_ENABLED; 
  780.     Buttons[2].fsStyle = TBSTYLE_BUTTON; 
  781.     Buttons[2].dwData = 0; 
  782.     Buttons[2].iString = 0; 
  783.  
  784.     Buttons[3].iBitmap = 2; 
  785.     Buttons[3].idCommand = ID_OPTIONS_VERTEXSELECTION; 
  786.     Buttons[3].fsState = TBSTATE_ENABLED; 
  787.     Buttons[3].fsStyle = TBSTYLE_BUTTON; 
  788.     Buttons[3].dwData = 0; 
  789.     Buttons[3].iString = 0; 
  790.  
  791.     Buttons[4].iBitmap = STD_HELP; 
  792.     Buttons[4].idCommand = 0; 
  793.     Buttons[4].fsState = TBSTATE_ENABLED; 
  794.     Buttons[4].fsStyle = TBSTYLE_SEP; 
  795.     Buttons[4].dwData = 0; 
  796.     Buttons[4].iString = 0; 
  797.  
  798.     Buttons[5].iBitmap = 3; 
  799.     Buttons[5].idCommand = ID_D3D_SOLID; 
  800.     Buttons[5].fsState = TBSTATE_ENABLED; 
  801.     Buttons[5].fsStyle = TBSTYLE_BUTTON; 
  802.     Buttons[5].dwData = 0; 
  803.     Buttons[5].iString = 0; 
  804.  
  805.     Buttons[6].iBitmap = 4; 
  806.     Buttons[6].idCommand = ID_D3D_WIREFRAME; 
  807.     Buttons[6].fsState = TBSTATE_ENABLED; 
  808.     Buttons[6].fsStyle = TBSTYLE_BUTTON; 
  809.     Buttons[6].dwData = 0; 
  810.     Buttons[6].iString = 0; 
  811.  
  812.     Buttons[7].iBitmap = 5; 
  813.     Buttons[7].idCommand = ID_D3D_EDGEMODE; 
  814.     Buttons[7].fsState = TBSTATE_ENABLED; 
  815.     Buttons[7].fsStyle = TBSTYLE_BUTTON; 
  816.     Buttons[7].dwData = 0; 
  817.     Buttons[7].iString = 0; 
  818.  
  819.     Buttons[8].iBitmap = STD_HELP; 
  820.     Buttons[8].idCommand = 0; 
  821.     Buttons[8].fsState = TBSTATE_ENABLED; 
  822.     Buttons[8].fsStyle = TBSTYLE_SEP; 
  823.     Buttons[8].dwData = 0; 
  824.     Buttons[8].iString = 0; 
  825.  
  826.     Buttons[9].iBitmap = 6; 
  827.     Buttons[9].idCommand = ID_D3D_ADJACENCYMODE; 
  828.     Buttons[9].fsState = TBSTATE_ENABLED; 
  829.     Buttons[9].fsStyle = TBSTYLE_BUTTON; 
  830.     Buttons[9].dwData = 0; 
  831.     Buttons[9].iString = 0; 
  832.  
  833.     Buttons[10].iBitmap = 7; 
  834.     Buttons[10].idCommand = ID_D3D_STRIPMODE; 
  835.     Buttons[10].fsState = TBSTATE_ENABLED; 
  836.     Buttons[10].fsStyle = TBSTYLE_BUTTON; 
  837.     Buttons[10].dwData = 0; 
  838.     Buttons[10].iString = 0; 
  839.  
  840.     Buttons[11].iBitmap = 8; 
  841.     Buttons[11].idCommand = ID_D3D_CREASEMODE; 
  842.     Buttons[11].fsState = TBSTATE_ENABLED; 
  843.     Buttons[11].fsStyle = TBSTYLE_BUTTON; 
  844.     Buttons[11].dwData = 0; 
  845.     Buttons[11].iString = 0; 
  846.  
  847.     Buttons[12].iBitmap = 9; 
  848.     Buttons[12].idCommand = ID_D3D_SHOWNORMALS; 
  849.     Buttons[12].fsState = TBSTATE_ENABLED; 
  850.     Buttons[12].fsStyle = TBSTYLE_BUTTON; 
  851.     Buttons[12].dwData = 0; 
  852.     Buttons[12].iString = 0; 
  853.  
  854.     Buttons[13].iBitmap = STD_HELP; 
  855.     Buttons[13].idCommand = 0; 
  856.     Buttons[13].fsState = TBSTATE_ENABLED; 
  857.     Buttons[13].fsStyle = TBSTYLE_SEP; 
  858.     Buttons[13].dwData = 0; 
  859.     Buttons[13].iString = 0; 
  860.  
  861.     Buttons[14].iBitmap = 10; 
  862.     Buttons[14].idCommand = ID_OPTIONS_INFO; 
  863.     Buttons[14].fsState = TBSTATE_ENABLED; 
  864.     Buttons[14].fsStyle = TBSTYLE_BUTTON; 
  865.     Buttons[14].dwData = 0; 
  866.     Buttons[14].iString = 0; 
  867.  
  868.     Buttons[15].iBitmap = STD_HELP; 
  869.     Buttons[15].idCommand = 0; 
  870.     Buttons[15].fsState = TBSTATE_ENABLED; 
  871.     Buttons[15].fsStyle = TBSTYLE_SEP; 
  872.     Buttons[15].dwData = 0; 
  873.     Buttons[15].iString = 0; 
  874.  
  875.     Buttons[16].iBitmap = 11; 
  876.     Buttons[16].idCommand = ID_VIEW_PLAYANIM; 
  877.     Buttons[16].fsState = TBSTATE_ENABLED; 
  878.     Buttons[16].fsStyle = TBSTYLE_BUTTON; 
  879.     Buttons[16].dwData = 0; 
  880.     Buttons[16].iString = 0; 
  881.  
  882.     Buttons[17].iBitmap = 12; 
  883.     Buttons[17].idCommand = ID_VIEW_PAUSEANIM; 
  884.     Buttons[17].fsState = TBSTATE_ENABLED; 
  885.     Buttons[17].fsStyle = TBSTYLE_BUTTON; 
  886.     Buttons[17].dwData = 0; 
  887.     Buttons[17].iString = 0; 
  888.  
  889.  
  890.     m_hwndToolbar = CreateToolbarEx(m_hwnd, WS_CHILD | WS_VISIBLE, 1, 15, m_hInstance, IDB_BITMAP1/*HINST_COMMCTRL, IDB_STD_SMALL_COLOR*/, Buttons, cButtons, 18, 17, 16, 15, sizeof(TBBUTTON));
  891.  
  892.     GetClientRect(m_hwndToolbar, &r);
  893. }
  894.  
  895. BOOL WINAPI D3DXDumpUnfreedMemoryInfo();
  896.  
  897. int APIENTRY
  898. WinMain( HINSTANCE hinst,
  899.          HINSTANCE hPrevInstance,
  900.          LPSTR lpCmdLine,
  901.          int nCmdShow )
  902. {
  903.     HRESULT hr;
  904.     WNDCLASS wndclass;
  905.     LPSTR szIcon = NULL;
  906.     char *szFilename;
  907.     char szFilenameBuffer[256];
  908.     BOOL bFilenameProvided = FALSE;
  909.     BOOL bForceSoftwareMode = FALSE;
  910.     BOOL bForceRefRast = FALSE;
  911.     DWORD dwWidth = 640;
  912.     DWORD dwHeight = 480;
  913.     BOOL bDisableHWNPatches = FALSE;
  914.     BOOL bAdjacencyMode = FALSE;
  915.     BOOL bStripMode = FALSE;
  916.     BOOL bNormalsMode = FALSE;
  917.     BOOL bCreaseMode = FALSE;
  918.                     
  919.     // Parse command line.
  920.     if(lpCmdLine)
  921.     {
  922.         LPCSTR pchMin, pchLim;
  923.         pchLim = lpCmdLine;
  924.  
  925.         for(;;)
  926.         {
  927.             for(pchMin = pchLim; *pchMin == ' '; pchMin++);
  928.             for(pchLim = pchMin; *pchLim != ' ' && *pchLim != '\0'; pchLim++)
  929.             {
  930.                 // check for quotes to ignore spaces
  931.                 if (*pchLim == '"')
  932.                 {
  933.                     pchLim++;
  934.                     while (*pchLim != '"' && *pchLim != '\0')
  935.                     {
  936.                         pchLim++;
  937.                     }
  938.                 }
  939.             }
  940.  
  941.             if(*pchMin == '\0')
  942.                 break;
  943.             if(*pchMin == '-' || *pchMin == '/')
  944.             {
  945.                 char szToken[16];
  946.                 int cchToken = 0;
  947.  
  948.                 for(pchMin++; pchMin < pchLim && cchToken < 15; pchMin++)
  949.                     szToken[cchToken++] = static_cast<char>(tolower(*pchMin));
  950.  
  951.                 szToken[cchToken] = '\0';
  952.  
  953.                 if ((strcmp(szToken, "sw") == 0) || (strcmp(szToken, "software") == 0))
  954.                 {
  955.                     bForceSoftwareMode = TRUE;
  956.                 }
  957.                 else if ((strcmp(szToken, "ref") == 0) || (strcmp(szToken, "reference") == 0))
  958.                 {
  959.                     bForceRefRast = TRUE;
  960.                 }
  961.                 else if (!memcmp(szToken, "w:", 2) || !memcmp(szToken, "width:", 6))
  962.                 {
  963.                     dwWidth = atoi(strchr(szToken, ':') + 1);
  964.                 }
  965.  
  966.                 else if (!memcmp(szToken, "h:", 2) || !memcmp(szToken, "height:", 7))
  967.                 {
  968.                     dwHeight = atoi(strchr(szToken, ':') + 1);
  969.                 }
  970.                 else if ((strcmp(szToken, "hd") == 0) || (strcmp(szToken, "hwnpatchesdisable") == 0))
  971.                 {
  972.                     bDisableHWNPatches = TRUE;
  973.                 }
  974.                 else if (strcmp(szToken, "a") == 0)
  975.                 {
  976.                     bAdjacencyMode = TRUE;
  977.                 }
  978.                 else if (strcmp(szToken, "s") == 0)
  979.                 {
  980.                     bStripMode = TRUE;
  981.                 }
  982.                 else if (strcmp(szToken, "n") == 0)
  983.                 {
  984.                     bNormalsMode = TRUE;
  985.                 }
  986.                 else if (strcmp(szToken, "r") == 0)
  987.                 {
  988.                     bCreaseMode = TRUE;
  989.                 }
  990.  
  991. #if 0
  992.  
  993.  
  994.                 if(!strcmp(szToken, "hal"))
  995.                 {
  996.                     m_pData->m_Options.m_bForceDevType = TRUE;
  997.                     m_pData->m_Options.m_DevType = D3DDEVTYPE_HAL;
  998.                 }
  999.  
  1000.                 else if(!strcmp(szToken, "emu") || !strcmp(szToken, "emulation") || !strcmp(szToken, "rgb"))
  1001.                 {
  1002.                     m_pData->m_Options.m_bForceDevType = TRUE;
  1003.                     m_pData->m_Options.m_DevType = D3DDEVTYPE_SW;
  1004.                 }
  1005.  
  1006.                 else if(!strcmp(szToken, "ref") || !strcmp(szToken, "reference"))
  1007.                 {
  1008.                     m_pData->m_Options.m_bForceDevType = TRUE;
  1009.                     m_pData->m_Options.m_DevType = D3DDEVTYPE_REF;
  1010.                 }
  1011.  
  1012.                 else if(!strcmp(szToken, "hw") || !strcmp(szToken, "hardware"))
  1013.                 {
  1014.                     m_pData->m_Options.m_bForceBehavior = TRUE;
  1015.                     m_pData->m_Options.m_dwBehavior |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
  1016.                 }
  1017.  
  1018.                 else if(!strcmp(szToken, "pure"))
  1019.                 {
  1020.                     m_pData->m_Options.m_bForceBehavior = TRUE;
  1021.                     m_pData->m_Options.m_dwBehavior |= D3DCREATE_PUREDEVICE;
  1022.                 }
  1023.  
  1024. #endif
  1025.             }
  1026.             else
  1027.             {
  1028.                 DWORD ich;
  1029.                 szFilename = szFilenameBuffer;
  1030.                 for(ich=0; pchMin < pchLim; pchMin++,ich++)
  1031.                     szFilename[ich] = *pchMin;
  1032.  
  1033.                 szFilename[ich] = '\0';
  1034.                 bFilenameProvided = TRUE;
  1035.  
  1036.                 // if there are quotes, then remove them
  1037.                 if ((szFilename[0] == '"') && (szFilename[ich-1] == '"'))
  1038.                 {
  1039.                     szFilename[ich-1] = '\0';
  1040.                     szFilename++;
  1041.                 }
  1042.             }
  1043.         }
  1044.     }
  1045.  
  1046.     wndclass.style         = CS_HREDRAW | CS_VREDRAW;
  1047.     wndclass.lpfnWndProc   = (WNDPROC) CD3DXApplication::WndProc;
  1048.     wndclass.cbClsExtra    = 0;
  1049.     wndclass.cbWndExtra    = 0;
  1050.     wndclass.hInstance     = hinst;
  1051.     wndclass.hIcon         = LoadIcon(hinst, MAKEINTRESOURCE(IDI_MAINICON));
  1052.     wndclass.hCursor       = CopyCursor(LoadCursor(NULL, IDC_ARROW));
  1053.     wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
  1054.     wndclass.lpszClassName = "MeshView";
  1055.     wndclass.lpszMenuName  = MAKEINTRESOURCE(IDR_MAINMENU);
  1056.     if (! RegisterClass(&wndclass) )
  1057.     {
  1058.         return FALSE;
  1059.     }
  1060.  
  1061.     InitFrameViewClass(hinst);
  1062.  
  1063.     // indent so that App will get destroyed before memory check
  1064.     {
  1065.         TrivialData App;
  1066.         g_pData = &App;
  1067.  
  1068.         if(FAILED(hr = App.Initialize(hinst, "MeshView", "MeshView", dwWidth, dwHeight)))
  1069.         {
  1070.             MessageBox(NULL, DXGetErrorString8(hr), "Error", MB_OK);
  1071.         }
  1072.  
  1073.         App.InitializeHelper();
  1074.  
  1075.         if (bFilenameProvided)
  1076.         {
  1077.             if( szFilename[1] != ':' &&
  1078.                 !(szFilename[0] == '\\' && szFilename[1] == '\\') )
  1079.             {
  1080.                 GetCurrentDirectory(sizeof(App.m_szInitialFilename), App.m_szInitialFilename);
  1081.                 strcat(App.m_szInitialFilename, "\\");
  1082.                 strcat(App.m_szInitialFilename, szFilename);
  1083.             }
  1084.             else
  1085.             {
  1086.                 strcpy(App.m_szInitialFilename, szFilename);
  1087.             }
  1088.  
  1089.             App.m_bInitialFilename = TRUE;
  1090.         }
  1091.  
  1092.         App.m_bForceSoftwareMode = bForceSoftwareMode;
  1093.         App.m_bForceRefRast = bForceRefRast;
  1094.         App.m_bDisableHWNPatches = bDisableHWNPatches;
  1095.         App.m_bAdjacencyMode = bAdjacencyMode;
  1096.         App.m_bStripMode = bStripMode;
  1097.         App.m_bNormalsMode = bNormalsMode;
  1098.         App.m_bCreaseMode = bCreaseMode;
  1099.  
  1100.         if (FAILED(hr = App.Run()))
  1101.         {
  1102.             MessageBox(NULL, DXGetErrorString8(hr), "Error", MB_OK);
  1103.         }
  1104.     }
  1105.  
  1106. //  GXASSERT(!D3DXDumpUnfreedMemoryInfo());
  1107.  
  1108.     D3DXDumpUnfreedMemoryInfo();
  1109.  
  1110.     return 0;
  1111. }
  1112.  
  1113.  
  1114.  
  1115. HRESULT
  1116. TrivialData::SetProjectionMatrix()
  1117. {
  1118.     D3DXMATRIX mat;
  1119.     RECT r;
  1120.  
  1121.     if (m_pdeHead == NULL)
  1122.         return S_OK;
  1123.  
  1124.     GetClientRect( m_hwnd, &r );
  1125.     r.top += 28;
  1126.     //r.bottom -= 48;
  1127.     r.bottom -= 20;
  1128.  
  1129.     float fAspect = (float)(r.right - r.left) / (float)(r.bottom - r.top);
  1130.  
  1131.     D3DXMatrixPerspectiveFovLH(&mat, 0.25f*3.141592654f, fAspect, m_pdeSelected->fRadius / 64, m_pdeSelected->fRadius * 200);
  1132.     return m_pDevice->SetTransform( D3DTS_PROJECTION, (D3DMATRIX*)&mat );
  1133. }
  1134.  
  1135.  
  1136. void
  1137. TrivialData::AdjustScrollbar()
  1138. {
  1139.     SCROLLINFO sbInfo;
  1140.     DWORD min,max,cur;
  1141.     sbInfo.cbSize = sizeof(SCROLLINFO);
  1142.     sbInfo.fMask = SIF_ALL;
  1143.  
  1144.     if (m_pmcSelectedMesh == NULL)
  1145.     {
  1146.         min = 0;
  1147.         max = 0;
  1148.         cur = 0;
  1149.         SendMessage(m_hwndStatus, SB_SETTEXT , (WPARAM) 1, (LPARAM) "Nothing Selected"); 
  1150.     }
  1151.     else if (m_pmcSelectedMesh->bPMMeshMode)
  1152.     {
  1153.         min = m_pmcSelectedMesh->pPMMesh->GetMinVertices();
  1154.         max = m_pmcSelectedMesh->pPMMesh->GetMaxVertices();
  1155.         cur = m_pmcSelectedMesh->pPMMesh->GetNumVertices();
  1156.         SendMessage(m_hwndStatus, SB_SETTEXT , (WPARAM) 1, (LPARAM) "PMesh Mode"); 
  1157.     }
  1158.     else if (m_pmcSelectedMesh->bSimplifyMode)
  1159.     {
  1160.         min = 1;
  1161.         max = m_pmcSelectedMesh->pSimpMesh->GetMaxVertices();
  1162.         cur = m_pmcSelectedMesh->pSimpMesh->GetNumVertices();
  1163.         SendMessage(m_hwndStatus, SB_SETTEXT , (WPARAM) 1, (LPARAM) "Simplify Mode"); 
  1164.     }
  1165.     else if (m_pmcSelectedMesh->bTesselateMode || m_pmcSelectedMesh->bNPatchMode)
  1166.     {
  1167.         min = 0;
  1168.         max = 32;
  1169.         cur = m_pmcSelectedMesh->cTesselateLevel;
  1170.  
  1171.         SendMessage(m_hwndStatus, SB_SETTEXT , (WPARAM) 1, (LPARAM) "N-Patch Mode"); 
  1172.     }
  1173.     else
  1174.     {
  1175.         min = 0;
  1176.         max = 0;
  1177.         cur = 0;
  1178.         SendMessage(m_hwndStatus, SB_SETTEXT , (WPARAM) 1, (LPARAM) "Polygon Mode"); 
  1179.     }
  1180.  
  1181.     cur = min + max - cur;
  1182.  
  1183.     sbInfo.nMin = min;
  1184.     sbInfo.nMax = max;
  1185.     sbInfo.nPage = 1;
  1186.     sbInfo.nPos = cur;
  1187.     sbInfo.nTrackPos = sbInfo.nMin;
  1188.  
  1189.     SetScrollInfo(m_hwnd, SB_VERT, &sbInfo, TRUE);
  1190.  
  1191.     SetupMenu();
  1192. }
  1193.  
  1194. HRESULT
  1195. TrivialData::UpdateTreeInfo(SFrame *pframeCur, HTREEITEM htreeParent)
  1196. {
  1197.     HRESULT hr = S_OK;
  1198.     SMeshContainer *pmcMesh;
  1199.     SFrame *pframeChild;
  1200.     char *szNameCur;
  1201.     HTREEITEM htreeCur;
  1202.  
  1203.     if (pframeCur->szName == NULL)
  1204.     {
  1205.         szNameCur = "Unnamed Frame";
  1206.     }
  1207.     else
  1208.     {
  1209.         szNameCur = pframeCur->szName;
  1210.     }
  1211.  
  1212.     pframeCur->m_hTreeHandle = m_pfvTreeView->InsertIntoTree(htreeParent, szNameCur, (PVOID)pframeCur);
  1213.  
  1214.     pmcMesh = pframeCur->pmcMesh;
  1215.     while (pmcMesh != NULL)
  1216.     {
  1217.         if (pmcMesh->Name == NULL)
  1218.         {
  1219.             szNameCur = "Unnamed Mesh";
  1220.         }
  1221.         else
  1222.         {
  1223.             szNameCur = pmcMesh->Name;
  1224.         }
  1225.  
  1226.         m_pfvTreeView->InsertIntoTree(pframeCur->m_hTreeHandle, szNameCur, (PVOID)pframeCur);
  1227.  
  1228.         pmcMesh = (SMeshContainer*)pmcMesh->pNextMeshContainer;
  1229.     }
  1230.  
  1231.     pframeChild = pframeCur->pframeFirstChild;
  1232.     while (pframeChild != NULL)
  1233.     {
  1234.         UpdateTreeInfo(pframeChild, pframeCur->m_hTreeHandle);
  1235.  
  1236.         pframeChild = pframeChild->pframeSibling;
  1237.     }
  1238.  
  1239.     return S_OK;
  1240. }
  1241.  
  1242. HRESULT
  1243. TrivialData::UpdateMeshMenu()
  1244. {
  1245.     HRESULT hr;
  1246.  
  1247. #if 0
  1248.     SDrawElement *pdeCur;
  1249.     UINT cMeshes;
  1250.     UINT iMesh;
  1251.  
  1252.     cMeshes = GetMenuItemCount(m_hMeshMenu);
  1253.     for (iMesh = 0; iMesh < cMeshes; iMesh++)
  1254.     {
  1255.         RemoveMenu(m_hMeshMenu, 0, MF_BYPOSITION);
  1256.     }
  1257.  
  1258.     iMesh = 0;
  1259.     pdeCur = m_pdeHead;
  1260.     while ((pdeCur != NULL) && (iMesh < 10))
  1261.     {
  1262.         if (pdeCur->szName != NULL)
  1263.             AppendMenu(m_hMeshMenu, MF_STRING, ID_MESH_1 + iMesh, pdeCur->szName);
  1264.         else
  1265.             AppendMenu(m_hMeshMenu, MF_STRING, ID_MESH_1 + iMesh, "<No Mesh Open>");
  1266.  
  1267.         pdeCur = pdeCur->pdeNext;
  1268.         iMesh += 1;
  1269.     }
  1270. #endif
  1271.  
  1272.     if (m_pfvTreeView != NULL)
  1273.     {
  1274.         // now update the tree control
  1275.         m_pfvTreeView->RemoveAllItems();
  1276.  
  1277.         if (m_pframeSelected != NULL)
  1278.         {
  1279.             hr = UpdateTreeInfo(m_pframeSelected, NULL);
  1280.             if (FAILED(hr))
  1281.                 return hr;
  1282.         }
  1283.     }
  1284.  
  1285.     return S_OK;
  1286. }
  1287.  
  1288. HRESULT
  1289. TrivialData::UpdateAnimationsMenu()
  1290. {
  1291.     HRESULT hr;
  1292.  
  1293.     UINT cAnimSets;
  1294.     UINT iAnimSet;
  1295.     LPD3DXANIMATIONSET pAnimSet;
  1296.     LPCTSTR szName;
  1297.  
  1298.     cAnimSets = GetMenuItemCount(m_hAnimationsMenu);
  1299.     for (iAnimSet = 0; iAnimSet < cAnimSets; iAnimSet++)
  1300.     {
  1301.         RemoveMenu(m_hAnimationsMenu, 0, MF_BYPOSITION);
  1302.     }
  1303.  
  1304.     if (m_pdeHead == NULL)
  1305.         return S_OK;
  1306.  
  1307.     if (m_pdeHead->m_pAnimMixer == NULL)
  1308.     {
  1309.         AppendMenu(m_hAnimationsMenu, MF_STRING, ID_ANIMATION_1 + iAnimSet, "No Animation");
  1310.     }
  1311.  
  1312.     if (m_pdeHead->m_pAnimMixer != NULL)
  1313.         cAnimSets = min(m_pdeHead->m_pAnimMixer->GetNumAnimationSets(), 50);
  1314.     else
  1315.         cAnimSets = 0;
  1316.  
  1317.     for (iAnimSet = 0; iAnimSet < cAnimSets; iAnimSet++)
  1318.     {
  1319.         m_pdeHead->m_pAnimMixer->GetAnimationSet(iAnimSet, &pAnimSet);
  1320.  
  1321.         szName = pAnimSet->GetName();
  1322.  
  1323.         if (szName != NULL)
  1324.             AppendMenu(m_hAnimationsMenu, MF_STRING, ID_ANIMATION_1 + iAnimSet, szName);
  1325.         else
  1326.             AppendMenu(m_hAnimationsMenu, MF_STRING, ID_ANIMATION_1 + iAnimSet, "<No Animation Name>");
  1327.  
  1328.         GXRELEASE(pAnimSet);
  1329.     }
  1330.  
  1331.     CheckMenuItem(m_hMenu, ID_ANIMATION_1 + m_pdeHead->m_iSelectedAnimSet, MF_CHECKED);
  1332.  
  1333.     return S_OK;
  1334. }
  1335.  
  1336. void
  1337. TrivialData::SelectDrawElement(SDrawElement *pdeNew)
  1338. {
  1339.     HRESULT hr;
  1340.  
  1341.     if (m_pdeSelected != pdeNew)
  1342.     {
  1343.         if (pdeNew != NULL)
  1344.         {
  1345.             m_pdeSelected = pdeNew;
  1346.  
  1347.             SelectFrame(pdeNew->pframeRoot, NULL);
  1348.             SelectFace(UNUSED32);
  1349.             SelectVertex(UNUSED32);
  1350.         }
  1351.         else
  1352.         {
  1353.             m_pdeSelected = NULL;
  1354.             m_pmcSelectedMesh = NULL;
  1355.             m_pframeSelected = NULL;
  1356.         }
  1357.  
  1358.         AdjustScrollbar();
  1359.         m_abArcBall.Reset();
  1360.  
  1361.         hr = UpdateMeshMenu();
  1362.         if (FAILED(hr))
  1363.             return;
  1364.     }
  1365. }
  1366.  
  1367. void
  1368. TrivialData::SwitchToAnimationSet(UINT iAnimSet)
  1369. {
  1370.     LPD3DXANIMATIONSET pAnim;
  1371.  
  1372.     GXASSERT(iAnimSet <= 50);
  1373.  
  1374.     CheckMenuItem(m_hMenu, ID_ANIMATION_1 + m_pdeHead->m_iSelectedAnimSet, MF_UNCHECKED);
  1375.     CheckMenuItem(m_hMenu, ID_ANIMATION_1 + iAnimSet, MF_CHECKED);
  1376.  
  1377.     m_pdeHead->m_iSelectedAnimSet = iAnimSet;
  1378.  
  1379.     // should only be NULL if a user clicked on a placeholder
  1380.     if (m_pdeHead->m_pAnimMixer != NULL)
  1381.     {
  1382.         m_pdeHead->m_pAnimMixer->GetAnimationSet(iAnimSet, &pAnim);
  1383.         m_pdeHead->m_pAnimMixer->SetTrackAnimationSet(0, pAnim);
  1384.         GXRELEASE(pAnim);
  1385.     }
  1386. }
  1387.  
  1388. #if 0
  1389. void
  1390. TrivialData::SwitchToMeshID(UINT iMeshID)
  1391. {
  1392.     UINT iMesh;
  1393.     UINT iCurMesh;
  1394.     SDrawElement *pdeCur;
  1395.  
  1396.     iMesh = iMeshID - ID_MESH_1;
  1397.     GXASSERT(iMesh <= 8);
  1398.  
  1399.     iCurMesh = 0;
  1400.     pdeCur = m_pdeHead;
  1401.     while ((pdeCur != NULL) && (iCurMesh < iMesh))
  1402.     {
  1403.             pdeCur = pdeCur->pdeNext;
  1404.             iCurMesh++;
  1405.     }
  1406.     GXASSERT(iCurMesh == iMesh);
  1407.     GXASSERT(pdeCur != NULL);
  1408.  
  1409.     SelectDrawElement(pdeCur);
  1410. }
  1411. #endif
  1412.  
  1413. DWORD GetVertexIndexFromBarycentric(float fU, float fV)
  1414. {
  1415.     float fOther = 1.0f - fU - fV;
  1416.  
  1417.     if (fU > fV)
  1418.     {
  1419.         if (fU > fOther)
  1420.         {
  1421.             return 1;
  1422.         }
  1423.         else
  1424.         {
  1425.             return 0;
  1426.         }
  1427.     }
  1428.     else 
  1429.     {
  1430.         if (fV > fOther)
  1431.         {
  1432.             return 2;
  1433.         }
  1434.         else
  1435.         {
  1436.             return 0;
  1437.         }
  1438.     }
  1439. }
  1440.  
  1441. BOOL BIntersectMeshContainer
  1442.     (
  1443.     SMeshContainer *pmcMesh,
  1444.     DWORD dwX, 
  1445.     DWORD dwY,
  1446.     D3DVIEWPORT9 *pViewport,
  1447.     D3DXMATRIX *pmatProjection,
  1448.     D3DXMATRIX *pmatView,
  1449.     D3DXMATRIX *pmatCombined,
  1450.     float *pfDistMin,
  1451.     SMeshContainer **ppmcHit,
  1452.     DWORD *pdwFaceHit,
  1453.     DWORD *pdwVertHit
  1454.     )
  1455. {
  1456.     HRESULT hr = S_OK;
  1457.     D3DXVECTOR3 vProjected;
  1458.     D3DXVECTOR3 vRayPos;
  1459.     D3DXVECTOR3 vRayDirection;
  1460.     float fDist= 0.0f;
  1461.     BOOL bHit= FALSE;
  1462.     BOOL bFound = FALSE;
  1463.     float fRayLength= 0.0f;
  1464.     DWORD dwFace= 0;
  1465.     float fU= 0.0f, fV= 0.0f;
  1466.     DWORD iVertexIndex= 0;
  1467.     PBYTE pbIndices= NULL;
  1468.     LPD3DXBASEMESH pMeshCur= NULL;
  1469.     PBYTE       pbVerticesSrc= NULL;
  1470.     PBYTE       pbVerticesDest= NULL;
  1471.     D3DXMATRIXA16* rgBoneMatrices= NULL;
  1472.  
  1473.     if ((pmcMesh != NULL) && (pmcMesh->m_pSkinnedMesh != NULL))  // there's a skinned mesh
  1474.     {
  1475.         // calculate ray position in world space
  1476.         vProjected = D3DXVECTOR3((float)dwX, (float)dwY, 0.0f);
  1477.         D3DXVec3Unproject(&vRayPos, &vProjected, pViewport, pmatProjection, pmatView, NULL);
  1478.  
  1479.  
  1480.         // calculate ray direction in world space
  1481.         vProjected = D3DXVECTOR3((float)dwX, (float)dwY, 1.0f);
  1482.         D3DXVec3Unproject(&vRayDirection, &vProjected, pViewport, pmatProjection, pmatView, NULL);
  1483.         vRayDirection -= vRayPos;
  1484.  
  1485.  
  1486.         // get the bone count
  1487.  
  1488.         DWORD   cBones  = pmcMesh->pSkinInfo->GetNumBones();
  1489.  
  1490.  
  1491.         // allocate bone transform array
  1492.  
  1493.         rgBoneMatrices  = new D3DXMATRIXA16[cBones];
  1494.  
  1495.         if (!rgBoneMatrices)
  1496.             return FALSE;
  1497.  
  1498.  
  1499.         // set up bone transforms
  1500.         
  1501.         for (DWORD iBone = 0; iBone < cBones; ++iBone)
  1502.         {
  1503.             D3DXMatrixMultiply
  1504.             (
  1505.                 &rgBoneMatrices[iBone],                         // output (world)
  1506.                 &pmcMesh->pBoneOffsetMatrices[iBone],   // bone offset matrix (world)
  1507.                 pmcMesh->m_pBoneMatrix[iBone]        // bone current transform (world)
  1508.             );
  1509.         }
  1510.  
  1511.         hr= pmcMesh->m_pOrigMesh->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&pbVerticesSrc);
  1512.         if (FAILED(hr))
  1513.         {
  1514.              pmcMesh->m_pOrigMesh->UnlockVertexBuffer();
  1515.             goto e_exit;
  1516.         }
  1517.         hr= pmcMesh->m_pSkinnedMesh->LockVertexBuffer(0, (LPVOID*)&pbVerticesDest);
  1518.         if (FAILED(hr))
  1519.         {
  1520.               pmcMesh->m_pOrigMesh->UnlockVertexBuffer();
  1521.             pmcMesh->m_pSkinnedMesh->UnlockVertexBuffer();
  1522.             goto e_exit;
  1523.         }
  1524.         // generate skinned mesh, use the system memory copy
  1525.         hr = pmcMesh->pSkinInfo->UpdateSkinnedMesh(rgBoneMatrices, NULL, pbVerticesSrc, pbVerticesDest);
  1526.         pmcMesh->m_pOrigMesh->UnlockVertexBuffer();
  1527.         pmcMesh->m_pSkinnedMesh->UnlockVertexBuffer();
  1528.         if (FAILED(hr))
  1529.         {
  1530.             delete[] rgBoneMatrices;
  1531.             rgBoneMatrices= NULL;
  1532.             goto e_exit;
  1533.         }
  1534.  
  1535.         // free bone transform array
  1536.         delete[] rgBoneMatrices;
  1537.         rgBoneMatrices= NULL;
  1538.  
  1539.         // perform ray-mesh intersection
  1540.         hr = D3DXIntersect(
  1541.                 pmcMesh->m_pSkinnedMesh,
  1542.                 &vRayPos, 
  1543.                 &vRayDirection, 
  1544.                 &bHit, 
  1545.                 &dwFace,
  1546.                 &fU,
  1547.                 &fV,
  1548.                 &fDist,
  1549.                 NULL,
  1550.                 NULL);
  1551.         if (FAILED(hr))
  1552.             return FALSE;
  1553.         if (bHit)       // intersection found
  1554.         {
  1555.             // normalize intersection distance
  1556.             fDist  /= D3DXVec3Length(&vRayDirection);
  1557.  
  1558.             if (fDist < *pfDistMin)     // intersection distance is the smallest seen so far
  1559.             {
  1560.                 // update smallest intersection distance & intersected frame
  1561.                 *pfDistMin  = fDist;
  1562.                 *ppmcHit = pmcMesh;
  1563.  
  1564. #if 0
  1565.                 *pdwFaceHit = UNUSED32;
  1566.                 *pdwVertHit = UNUSED32;
  1567. #else
  1568.                 *pdwFaceHit = dwFace;
  1569.  
  1570.                 iVertexIndex = GetVertexIndexFromBarycentric(fU, fV);
  1571.                 pmcMesh->m_pSkinnedMesh->LockIndexBuffer(D3DLOCK_READONLY, (LPVOID*)&pbIndices);
  1572.  
  1573.                 if (pmcMesh->m_pSkinnedMesh->GetOptions() & D3DXMESH_32BIT)
  1574.                     *pdwVertHit = ((DWORD*)pbIndices)[dwFace * 3 + iVertexIndex];
  1575.                 else
  1576.                     *pdwVertHit = ((WORD*)pbIndices)[dwFace * 3 + iVertexIndex];
  1577.  
  1578.                 pmcMesh->m_pSkinnedMesh->UnlockIndexBuffer();
  1579. #endif
  1580.                 // indicate that we found a new smallest intersection distance
  1581.                 bFound      = TRUE;
  1582.             }
  1583.         }
  1584.     }
  1585.     else if ((pmcMesh != NULL) && (pmcMesh->ptmDrawMesh != NULL) && (pmcMesh->pSkinInfo == NULL))
  1586.     {
  1587.         pMeshCur = (pmcMesh->bNPatchMode) ? pmcMesh->pMeshToTesselate : pmcMesh->ptmDrawMesh;
  1588.  
  1589.         // calculate two points 
  1590.         vProjected = D3DXVECTOR3((float)dwX, (float)dwY, 0.0f);
  1591.         D3DXVec3Unproject(&vRayPos, &vProjected, pViewport, pmatProjection, pmatView, pmatCombined);
  1592.  
  1593.         vProjected = D3DXVECTOR3((float)dwX, (float)dwY, 1.0f);
  1594.         D3DXVec3Unproject(&vRayDirection, &vProjected, pViewport, pmatProjection, pmatView, pmatCombined);
  1595.  
  1596.         // subtract
  1597.         vRayDirection -= vRayPos;
  1598.  
  1599. #if 1
  1600.         LPD3DXBUFFER pbufAllHits;
  1601.         DWORD cHits;
  1602.  
  1603.         hr = D3DXIntersect(pMeshCur,
  1604.             &vRayPos, &vRayDirection, &bHit, &dwFace, &fU, &fV, &fDist, &pbufAllHits, &cHits);
  1605.         if (FAILED(hr))
  1606.             goto e_exit;
  1607.  
  1608.         GXRELEASE(pbufAllHits);
  1609. #else
  1610.         DWORD iAttrib;
  1611.         for (iAttrib = 0; iAttrib < pmcMesh->m_cAttributeGroups; iAttrib++)
  1612.         {
  1613.             hr = D3DXIntersectSubset(pMeshCur, iAttrib,
  1614.                 &vRayPos, &vRayDirection, &bHit, &dwFace, &fU, &fV, &fDist, NULL, NULL);
  1615.             if (FAILED(hr))
  1616.                goto e_exit;
  1617.  
  1618.             if (bHit)
  1619.                 break;
  1620.         }
  1621. #endif
  1622.         if (bHit)
  1623.         {
  1624.             // normalize the distance to be based on the length of the ray
  1625.             //  used to ignore scale factors in world matrices
  1626.             fRayLength = D3DXVec3Length(&vRayDirection);
  1627.             fDist /= fRayLength;
  1628.  
  1629.             if (fDist < *pfDistMin)
  1630.             {
  1631.                 *pfDistMin = fDist;
  1632.                 *ppmcHit = pmcMesh;
  1633.                 *pdwFaceHit = dwFace;
  1634.  
  1635.                 iVertexIndex = GetVertexIndexFromBarycentric(fU, fV);
  1636.                 pMeshCur->LockIndexBuffer(D3DLOCK_READONLY, (LPVOID*)&pbIndices);
  1637.  
  1638.                 if (pMeshCur->GetOptions() & D3DXMESH_32BIT)
  1639.                     *pdwVertHit = ((DWORD*)pbIndices)[dwFace * 3 + iVertexIndex];
  1640.                 else
  1641.                     *pdwVertHit = ((WORD*)pbIndices)[dwFace * 3 + iVertexIndex];
  1642.  
  1643.                 pMeshCur->UnlockIndexBuffer();
  1644.  
  1645.                 bFound = TRUE;
  1646.             }
  1647.         }
  1648.     }
  1649. e_exit:
  1650.  
  1651.     return bFound;
  1652. }
  1653.  
  1654.  
  1655. BOOL BIntersectFrame
  1656.     (
  1657.     SFrame *pframeCur,
  1658.     DWORD dwX, 
  1659.     DWORD dwY,
  1660.     D3DVIEWPORT9 *pViewport,
  1661.     D3DXMATRIX *pmatProjection,
  1662.     D3DXMATRIX *pmatView,
  1663.     float *pfDistMin,
  1664.     SFrame **ppframeHit,
  1665.     SMeshContainer **ppmcHit,
  1666.     DWORD *pdwFaceHit,
  1667.     DWORD *pdwVertHit
  1668.     )
  1669. {
  1670.     BOOL bFound = FALSE;
  1671.     SMeshContainer *pmcCur;
  1672.  
  1673.     pmcCur = pframeCur->pmcMesh;
  1674.  
  1675.     while (pmcCur != NULL)
  1676.     {
  1677.         if (BIntersectMeshContainer(pmcCur, dwX, dwY, pViewport, pmatProjection, pmatView, &pframeCur->matCombined, pfDistMin, ppmcHit, pdwFaceHit, pdwVertHit))
  1678.         {
  1679.             *ppframeHit = pframeCur;
  1680.             bFound = TRUE;
  1681.         }
  1682.         pmcCur = (SMeshContainer*)pmcCur->pNextMeshContainer;
  1683.     }
  1684.  
  1685.     if (pframeCur->pframeSibling != NULL)
  1686.     {
  1687.         if (BIntersectFrame(pframeCur->pframeSibling, dwX, dwY, pViewport, pmatProjection, pmatView, pfDistMin, ppframeHit, ppmcHit, pdwFaceHit, pdwVertHit))
  1688.         {
  1689.             bFound = TRUE;
  1690.         }
  1691.     }
  1692.     
  1693.     if (pframeCur->pframeFirstChild != NULL)
  1694.     {
  1695.         if (BIntersectFrame(pframeCur->pframeFirstChild, dwX, dwY, pViewport, pmatProjection, pmatView, pfDistMin, ppframeHit, ppmcHit, pdwFaceHit, pdwVertHit))
  1696.         {
  1697.             bFound = TRUE;
  1698.         }
  1699.     }
  1700.  
  1701.     return bFound;
  1702. }
  1703.  
  1704. void
  1705. TrivialData::SelectionChange
  1706.     (
  1707.     DWORD dwX, 
  1708.     DWORD dwY
  1709.     )
  1710. {
  1711.     HRESULT hr = S_OK;
  1712.  
  1713.     D3DXVECTOR3 vProjected;
  1714.     D3DXVECTOR3 vRayPos;
  1715.     D3DXVECTOR3 vRayDirection;
  1716.     D3DXVECTOR3 vVertHitPos;
  1717.     D3DVIEWPORT9 Viewport;
  1718.     D3DXMATRIX matProjection, matView, matWorld;
  1719.     SDrawElement *pdeCur= NULL;
  1720.     SDrawElement *pdeMin= NULL;
  1721.     SFrame *pframeMin= NULL;
  1722.     SMeshContainer *pmcMin= NULL;
  1723.     float fDistMin= 0.0f;
  1724.     DWORD dwFaceHit= 0;
  1725.     DWORD dwVertHit= 0;
  1726.  
  1727.     // account for toolbar
  1728.     dwY -= 28;
  1729.  
  1730.     m_pDevice->GetViewport(&Viewport);
  1731.     m_pDevice->GetTransform(D3DTS_VIEW, &matView);
  1732.     m_pDevice->GetTransform(D3DTS_PROJECTION, &matProjection);
  1733.  
  1734.     pdeMin = NULL;
  1735.     pdeCur = m_pdeHead;
  1736.     fDistMin = (float)HUGE_VAL;
  1737.     while (pdeCur != NULL)
  1738.     {
  1739.         // calculate two points 
  1740.         vProjected = D3DXVECTOR3((float)dwX, (float)dwY, 0.0f);
  1741.         D3DXVec3Unproject(&vRayPos, &vProjected, &Viewport, &matProjection, &matView, &pdeCur->pframeRoot->matCombined);
  1742.  
  1743.         vProjected = D3DXVECTOR3((float)dwX, (float)dwY, 1.0f);
  1744.         D3DXVec3Unproject(&vRayDirection, &vProjected, &Viewport, &matProjection, &matView, &pdeCur->pframeRoot->matCombined);
  1745.  
  1746.         // subtract
  1747.         vRayDirection -= vRayPos;
  1748.  
  1749.         // TODO:  the following check needs to be removed
  1750.         //if (1 || D3DXSphereBoundProbe(&pdeCur->vCenter, pdeCur->fRadius, &vRayPos, &vRayDirection))
  1751.         {
  1752.             if (BIntersectFrame(pdeCur->pframeRoot, dwX, dwY, &Viewport, &matProjection, &matView, &fDistMin, &pframeMin, &pmcMin, &dwFaceHit, &dwVertHit))
  1753.             {
  1754.                 pdeMin = pdeCur;
  1755.             }
  1756.         }
  1757.  
  1758.         pdeCur = pdeCur->pdeNext;
  1759.     }
  1760.  
  1761.     // if pdeMin != NULL then switch to that mesh, otherwise switch to no selection
  1762.     if (pdeMin != NULL)
  1763.         SelectDrawElement(pdeMin);
  1764.  
  1765.     if ((pdeMin != NULL) && (pframeMin != NULL))
  1766.     {        
  1767.         SelectFrame(pframeMin, pmcMin);
  1768.         SelectFace(dwFaceHit);
  1769.         SelectVertex(dwVertHit);
  1770.     }
  1771.  
  1772.     UpdateSelectionInfo();
  1773. }
  1774.  
  1775. void
  1776. TrivialData::UpdateSelectionInfo()
  1777. {
  1778.     char szBuf[80];
  1779.     PBYTE pbFaces;
  1780.     char rgszAdj[3][30];
  1781.     DWORD rgdwFace[3];
  1782.     DWORD iPoint;
  1783.     BOOL b16BitIndex;
  1784.  
  1785.     if (m_bVertexSelectionMode)
  1786.     {
  1787.         if (m_dwVertexSelected != UNUSED32)
  1788.         {
  1789.             if (m_pmcSelectedMesh->ptmDrawMesh != NULL)
  1790.             {
  1791.                 sprintf(szBuf, "Vertex %d", m_dwVertexSelected);
  1792.             }
  1793.             else
  1794.             {
  1795.                 sprintf(szBuf, "Vertex %d", m_dwVertexSelected);
  1796.             }
  1797.         }
  1798.         else
  1799.         {
  1800.             sprintf(szBuf, "No vertex selected");
  1801.         }
  1802.     }
  1803.     else if (m_bFaceSelectionMode)
  1804.     {
  1805.         if (m_dwFaceSelected != UNUSED32)
  1806.         {
  1807.             if (m_pmcSelectedMesh->ptmDrawMesh != NULL)
  1808.             {
  1809.                 b16BitIndex = !(m_pmcSelectedMesh->ptmDrawMesh->GetOptions() & D3DXMESH_32BIT);
  1810.                 m_pmcSelectedMesh->ptmDrawMesh->LockIndexBuffer(D3DLOCK_READONLY, (LPVOID*)&pbFaces);
  1811.  
  1812.                 for (iPoint = 0; iPoint < 3; iPoint++)
  1813.                 {
  1814.                     if (b16BitIndex)
  1815.                         rgdwFace[iPoint] = ((UINT16*)pbFaces)[m_dwFaceSelected * 3 + iPoint];
  1816.                     else
  1817.                         rgdwFace[iPoint] = ((UINT32*)pbFaces)[m_dwFaceSelected * 3 + iPoint];
  1818.  
  1819.                     if (m_pmcSelectedMesh->rgdwAdjacency != NULL)
  1820.                     {
  1821.                         if (m_pmcSelectedMesh->rgdwAdjacency[m_dwFaceSelected * 3 + iPoint] == UNUSED32)
  1822.                             sprintf(rgszAdj[iPoint], "UNUSED");
  1823.                         else
  1824.                             sprintf(rgszAdj[iPoint], "%d", m_pmcSelectedMesh->rgdwAdjacency[m_dwFaceSelected * 3 + iPoint]);
  1825.                     }
  1826.                     else
  1827.                     {
  1828.                         sprintf(rgszAdj[iPoint], "UNUSED");
  1829.                     }
  1830.                 }
  1831.  
  1832.                 m_pmcSelectedMesh->ptmDrawMesh->UnlockIndexBuffer();
  1833.  
  1834.                 sprintf(szBuf, "Face %d  Ind (%d, %d, %d) Adj (%s, %s, %s)\n", m_dwFaceSelected, 
  1835.                                             rgdwFace[0], rgdwFace[1], rgdwFace[2],
  1836.                                              rgszAdj[0],  rgszAdj[1],  rgszAdj[2]);
  1837.             }
  1838.             else
  1839.             {
  1840.                 sprintf(szBuf, "Face %d\n", m_dwFaceSelected);
  1841.             }
  1842.         }
  1843.         else
  1844.         {
  1845.             sprintf(szBuf, "No face selected");
  1846.         }
  1847.     }
  1848.     else
  1849.     {
  1850.         if ((m_pmcSelectedMesh != NULL) && (m_pmcSelectedMesh->Name != NULL))
  1851.         {
  1852.             strncpy(szBuf, m_pmcSelectedMesh->Name, sizeof(szBuf));
  1853.             szBuf[sizeof(szBuf)-1] = '\0';
  1854.         }
  1855.         else
  1856.         {
  1857.             szBuf[0] = '\0';
  1858.         }
  1859.     }
  1860.  
  1861.     SendMessage(m_hwndStatus, SB_SETTEXT , (WPARAM) 0, (LPARAM) szBuf); 
  1862. }
  1863.